﻿using System;
using System.Collections.Generic;

namespace ch06.binary.interpreter
{
    public readonly struct OperandStack
    {
        internal readonly Stack<ulong> Slots;

        public OperandStack(Stack<ulong> slot)
        {
            this.Slots = slot;
        }

        internal void PushU64(ulong val)
        {
            Slots.Push(val);
        }

        internal ulong PopU64()
        {
            return Slots.Pop();
        }

        public void PushS64(long val)
        {
            PushU64((ulong) val);
        }

        internal long PopS64()
        {
            return (long) PopU64();
        }

        internal void pushU32(uint val)
        {
            PushU64(val);
        }

        internal uint popU32()
        {
            return (uint) PopU64();
        }


        internal void pushS32(int val)
        {
            pushU32((uint) val);
        }

        internal int popS32()
        {
            return (int) popU32();
        }


        internal void pushF32(float val)
        {
            var bytes = BitConverter.GetBytes(val);
            pushU32(BitConverter.ToUInt32(bytes));
        }

        internal float popF32()
        {
            var bytes = BitConverter.GetBytes(popU32());
            return BitConverter.ToSingle(bytes);
        }

        internal void pushF64(double val)
        {
            var bytes = BitConverter.GetBytes(val);
            PushU64(BitConverter.ToUInt64(bytes));
        }

        internal double popF64()
        {
            var bytes = BitConverter.GetBytes(PopU64());
            return BitConverter.ToDouble(bytes);
        }

        internal void pushBool(bool val)
        {
            PushU64(val ? 1ul : 0ul);
        }

        internal bool popBool()
        {
            return PopU64() != 0ul;
        }
    }
}